package cn.itcast.order.web.ijpay;

import cn.itcast.order.common.ApiConstants;
import cn.itcast.order.common.OrderState;
import cn.itcast.order.common.ResponseResult;
import cn.itcast.order.config.ijpay.alipay.AliPayBean;
import cn.itcast.order.config.ijpay.alipay.AlipayApiConfigProperties;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.service.OrderService;
import cn.itcast.order.vo.IJPayVO;
import cn.itcast.order.web.ijpay.ijpayconfig.AbsAliPayApiConfig;
import cn.itcast.usercontext.interceptor.LoginCheck;
import cn.itcast.usercontext.interceptor.NoLoginCheck;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.alipay.AliPayApiConfig;
import com.ijpay.alipay.AliPayApiConfigKit;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @author sxt
 * @version 1.0
 * @description 支付宝 支付相关接口
 * @date 2024/4/26 18:27
 */
@Slf4j
@RestController
@LoginCheck
@RequestMapping(ApiConstants.ALIPAY_PREFIX)
public class AliPayIJPayController extends AbsAliPayApiConfig {
    @Resource
    private OrderService orderService;

    private AliPayBean aliPayBean;

    @Autowired
    public void setAliPayBean(AlipayApiConfigProperties aliPayApiConfigProperties) {
        this.aliPayBean = aliPayApiConfigProperties.getAliPayConfigs().get(0);
    }

    /**
     * 支付完成后支付宝会请求这个地址，由此我们可以来修改数据库中的订单状态
     */
    private final static String NOTIFY_URL = ApiConstants.ALIPAY_PREFIX + "/cert_notify_url";
    /**
     * 网站在支付完成后会跳转到这个地址
     */
    private final static String RETURN_URL = ApiConstants.ALIPAY_PREFIX + "/cert_return_url";
    /**
     * RETURN_URL的基础上重定向的地址
     */
    private final static String REDIRECT_URL = "/pay-success.html?";


    @Override
    public AliPayApiConfig getDefaultApiConfig() {
        return getApiConfig(aliPayBean.getAppId());
    }

    @GetMapping(value = "/pcPay")
    @ApiOperation("支付宝pc支付")
    @NoLoginCheck
    @ApiImplicitParam(name = "orderId", value = "订单id", required = true)
    public void pcPay(HttpServletResponse response, @RequestParam Long orderId) {
        Order order = orderService.queryOrderById(orderId);
        if (order == null) {
            return;
        }
        if (!(order.getState() == OrderState.ORDER_CREATED.getValue())) {
            return;
        }
        String outTradeNo = orderId.toString();
        String totalAmount = order.getMoney().toString();

        try {
//            AliPayApiConfigKit.setThreadLocalAliPayApiConfig(getDefaultApiConfig());

            AlipayTradePagePayModel model = new AlipayTradePagePayModel();
            model.setOutTradeNo(outTradeNo);
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
            model.setTotalAmount(totalAmount);
            model.setSubject("byz.com 订单编号" + outTradeNo);
            model.setBody("外部订单号：" + orderId + " 使用Alipay交易，金额为： " + totalAmount);
            model.setPassbackParams("passback_params");

            String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL;
            String returnUrl = aliPayBean.getDomain() + RETURN_URL;
            AliPayApi.tradePage(response, model, notifyUrl, returnUrl);
            // 之后将订单状态更新
            orderService.updateOrderState(order);
        } catch (Exception e) {
            log.error(e.getMessage());
        }

    }

    @GetMapping(value = "/tradeRefund")
    @NoLoginCheck
    @ApiOperation("支付宝退款")
    public ResponseResult tradeRefund(@RequestParam String orderId, @RequestParam String paymentInnerId) {
        try {
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(orderId);
            model.setTradeNo(paymentInnerId);

            model.setRefundAmount("10");
            model.setRefundReason("正常退款");
            System.out.println(AliPayApi.tradeRefundToResponse(model).getBody());
            JSONObject responseBody = JSONObject.parseObject(AliPayApi.tradeRefundToResponse(model).getBody());
            JSONObject alipayTradeRefundResponse = JSONObject.parseObject(responseBody.getString("alipay_trade_refund_response"));
            String code = alipayTradeRefundResponse.getString("code");
            String msg = alipayTradeRefundResponse.getString("msg");
            if ("10000".equals(code)) {
                String gmtRefundPay = alipayTradeRefundResponse.getString("gmt_refund_pay");
                boolean success = gmtRefundPay != null;
                IJPayVO alipayApiVO = new IJPayVO(code, msg, null, null, success);
                return ResponseResult.success(null, alipayApiVO);
            } else {
                String subMsg = alipayTradeRefundResponse.getString("sub_msg");
                String subCode = alipayTradeRefundResponse.getString("sub_code");
                IJPayVO alipayApiVO = new IJPayVO(code, msg, subCode, subMsg, false);
                return ResponseResult.success(alipayApiVO);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResponseResult.error(e.getMessage());
        }
    }

    @PostMapping(value = "/cert_notify_url")
    @NoLoginCheck
    @ApiOperation("支付宝异步回调接口（前端请忽略此接口）")
    public String certNotifyUrl(HttpServletRequest request) {
        log.error("进入cert_notify_url=======================");
        try {
            Map<String, String> params = AliPayApi.toMap(request);

            for (Map.Entry<String, String> entry : params.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }

            boolean verifyResult = AlipaySignature.rsaCertCheckV1(params, aliPayBean.getAliPayCertPath(), "UTF-8", "RSA2");

            if (verifyResult) {
                System.out.println("certNotifyUrl 验证成功succcess");

                // 更改支付完成状态
                Order outOrder = orderService.queryOrderById(Long.parseLong(params.get("out_trade_no")));
                if (outOrder != null && outOrder.getState() == OrderState.PAY_ING.getValue()) {
                    orderService.updateOrderState(outOrder);
                }

                return "success";
            } else {
                System.out.println("certNotifyUrl 验证失败");
                return "failure";
            }
        } catch (AlipayApiException e) {
            log.error(e.getMessage());
            return "failure";
        }
    }

    @GetMapping(value = "/cert_return_url")
    @NoLoginCheck
    @ApiOperation("支付宝支付成功后的跳转地址（前端请忽略此接口）")
    public String certReturnUrl(HttpServletRequest request, HttpServletResponse response) {
        log.error("进入cert_return_url=======================");
        try {
            Map<String, String> map = AliPayApi.toMap(request);
            for (Map.Entry<String, String> entry : map.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }

            boolean verifyResult = AlipaySignature.rsaCertCheckV1(map, aliPayBean.getAliPayCertPath(), "UTF-8",
                    "RSA2");

            if (verifyResult) {
                System.out.println("certReturnUrl 验证成功");
                String outTradeNo = map.get("out_trade_no");
                String tradeNo = map.get("trade_no");
//                OrderPaymentParam orderPaymentParam = new OrderPaymentParam(Long.parseLong(outTradeNo), PaymentMethodEnum.ALiPay.getCode(), tradeNo, null);
//                orderService.updateOrderPaymentInfo(orderPaymentParam);
                String redirectUrl = REDIRECT_URL
                        + "orderId=" + outTradeNo + "&"
                        + "paymentInnerId=" + tradeNo;
                response.sendRedirect(redirectUrl);
                return "success";
            } else {
                System.out.println("certReturnUrl 验证失败");
                return "failure";
            }
        } catch (IOException e) {
            log.error(e.getMessage());
            return "redirect failed";
        } catch (AlipayApiException e) {
            log.error(e.getMessage());
            return "failure";
        }
    }

}
